// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Functions to evaluate expectations with actual protocol buffers or
// actual values to see if the expectations are met.

#ifndef GOOGLE_PROTOBUF_EXPECTATION_EXPECTATION_EVAL_H_
#define GOOGLE_PROTOBUF_EXPECTATION_EXPECTATION_EVAL_H_

#include <string>
#include <vector>

namespace google {
namespace protobuf {

class EnumValueDescriptor;
class FieldDescriptor;
class Message;

}  // namespace protobuf
}  // namespace google

namespace google {
namespace protobuf_expectation {

class FieldExpectation;
class MessageExpectation;
class RepeatedMessageExpectation;
class RepeatedValueExpectation;
class ValueExpectation;

// Note that EvaluationResult.{expected,actual} are for human-readable outputs
// and you should not do, for example, regexp matching on these strings
// for any purpose. These strings could change at any time without notice for
// better human-readability.
struct EvaluationResult {
  std::string field;
  std::string expected;
  std::string actual;
  bool success;
};

// Each Evaluate() function returns a bool value which tells you if all
// expectations are met or not, and when it failed you can look into
// a vector of EvaluationResult to see which expectation among several things
// has failed.
bool Evaluate(const FieldExpectation& expectation,
              const protobuf::Message& message,
              std::vector<EvaluationResult>* eval_results);

bool Evaluate(const ValueExpectation& expectation,
              const protobuf::Message& message,
              const protobuf::FieldDescriptor* field,
              int index,
              std::vector<EvaluationResult>* eval_results);
template<typename T>
bool Evaluate(const ValueExpectation& expectation, T value,
              std::vector<EvaluationResult>* eval_results);
template<>
bool Evaluate<bool>(const ValueExpectation& expectation, bool value,
                    std::vector<EvaluationResult>* eval_results);
template<>
bool Evaluate<const protobuf::EnumValueDescriptor*>(
    const ValueExpectation& expectation,
    const protobuf::EnumValueDescriptor* value,
    std::vector<EvaluationResult>* eval_results);
bool Evaluate(const ValueExpectation& expectation,
              const std::string& value,
              std::vector<EvaluationResult>* eval_results);
inline bool Evaluate(const ValueExpectation& expectation,
                     const char* value,
                     std::vector<EvaluationResult>* eval_results) {
  return Evaluate(expectation, std::string(value), eval_results);
}

bool Evaluate(const MessageExpectation& expectation,
              const protobuf::Message& message,
              std::vector<EvaluationResult>* eval_results);

bool Evaluate(const RepeatedValueExpectation& expectation,
              const protobuf::Message& message,
              const protobuf::FieldDescriptor* field,
              std::vector<EvaluationResult>* eval_results);

bool Evaluate(const RepeatedMessageExpectation& expectation,
              const protobuf::Message& message,
              const protobuf::FieldDescriptor* field,
              std::vector<EvaluationResult>* eval_results);

}  // namespace protobuf_expectation
}  // namespace google

#endif  // GOOGLE_PROTOBUF_EXPECTATION_EXPECTATION_EVAL_H_
